import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServe {//TCP协议服务器
    private ServerSocket serverSocket=null;//相当于拉客的销售小哥
    public TcpEchoServe(int port) throws IOException {
        serverSocket=new ServerSocket(port);//指定服务器端口
    }
    public void start() throws IOException {
        System.out.println("服务器启动成功");
        Socket cliebtSocket=serverSocket.accept();//为当前客户端分配销售小姐姐
        processConnection(cliebtSocket);//在方法中执行,简洁好看
    }

    private void processConnection(Socket cliebtSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线\n",cliebtSocket.getInetAddress().toString(),cliebtSocket.getPort());
        try(InputStream inputStream=cliebtSocket.getInputStream();
            OutputStream outputStream=cliebtSocket.getOutputStream();) {//方便系统自动关闭资源文件
            Scanner scanner=new Scanner(inputStream);//获取客户端请求的输入流
            PrintWriter printWriter=new PrintWriter(outputStream);//转化为字符流,好操作
            while (true){
                if (!scanner.hasNext()){//若没有下一个了,即客户端断开连接下线了
                    System.out.printf("[%s:%d] 客户端下线",cliebtSocket.getInetAddress().toString(),cliebtSocket.getPort());//客户端下线
                    break;
                }
                //客户端正常运行情况
                String request=scanner.next();//读取客户端输入流的响应
                String response=process(request);//处理响应的方法
                printWriter.println(response);//给客户端回复,注意一定要使用换行形式的(println),因为约定了的
                printWriter.flush();//刷新缓冲区,马上发送出去
                System.out.printf("[%s:%d] req:%s;resp:%s\n",cliebtSocket.getInetAddress().toString(),cliebtSocket.getPort(),request,response);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private String process(String request) {//因为是回显程序,所以直接返回即可
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServe tcpEchoServe=new TcpEchoServe(9090);
        tcpEchoServe.start();
    }
}
//使用多线程搭建服务器,以便能同时启动多个客户端+
class TcpEchoServe1{
    ServerSocket serverSocketsocket=null;//网络通信必备
    public TcpEchoServe1(int port) throws IOException {//构造方法中初始化服务器端口
        serverSocketsocket=new ServerSocket(port);//
    }
    public void start() throws IOException {
        System.out.println("服务器启动成功");
        while (true){
            Socket socket=serverSocketsocket.accept();//分配小姐姐
            Thread thread=new Thread(()->{
                processConnection(socket);//在创建的线程中启动processconnectino方法,就不会启动不了多客户端的情况了
            });
            thread.start();//启动线程
        }
    }

    private void processConnection(Socket socket) {
        try(InputStream inputStream=socket.getInputStream();
        OutputStream outputStream=socket.getOutputStream();) {
            Scanner scanner=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);//包装一下,方便
            while (true){
                if (!scanner.hasNext()){
                    System.out.println("客户端下线");
                    break;
                }
                //客户端正常在线情况
                String request=scanner.next();//读取客户端请求
                String response=process(request);
                printWriter.println(response);//发送响应
                printWriter.flush();//马上发送
                System.out.printf("[%s:%d] req:%s  resp:%s\n",socket.getInetAddress(),socket.getPort(),request,response);;
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    private String process(String request) {//回显程序
        return request;
    }

    public static void main(String[] args) {
        try {
            TcpEchoServe1 tcpEchoServe1=new TcpEchoServe1(9090);
            tcpEchoServe1.start();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
class TcpEchoServe2{//使用线程池创建
    ServerSocket serverSocket=null;
    public TcpEchoServe2(int port){
        try {
            serverSocket=new ServerSocket(port);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public void start(){
        ExecutorService pool= Executors.newCachedThreadPool();//创建线程池
        System.out.println("服务器启动");
        while (true){
            try {
                Socket socket=serverSocket.accept();
                pool.submit(new Runnable() {//把线程放入线程池中
                    @Override
                    public void run() {
                        processConnection(socket);
                    }
                });
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private void processConnection(Socket socket)  {
        try (InputStream inputStream=socket.getInputStream();
        OutputStream outputStream=socket.getOutputStream();){
            Scanner scanner=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);//包装,好操作
            while (true){
                if(!scanner.hasNext()){
                    System.out.println("客户端下线");
                    break;
                }
                String request=scanner.next();//读取客户端请求
                String response=process(request);//处理响应
                printWriter.println(response);//发送响应回客户端
                printWriter.flush();//刷新缓冲区,马上发送
                System.out.printf("[%s:%d] req:%s resp:%s",socket.getInetAddress(),socket.getPort(),request,response);
            }


    }catch (IOException e){
            e.printStackTrace();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) {
        TcpEchoServe2 tcpEchoServe2=new TcpEchoServe2(9090);
        tcpEchoServe2.start();
    }

}
